package main

import (
	"log"
	"os"
	"runtime"
)

type LoggerI interface {
	Printf(format string, v ...interface{})
}

const MAX_SATCK_SIZE = 10

func PrintPanicStack(logger LoggerI) {
	if err := recover(); err != nil {
		logger.Printf("%v", err)
		for i := 0; i < MAX_SATCK_SIZE; i++ {
			funcName, fileName, line, ok := runtime.Caller(i)
			if ok {
				logger.Printf("frame %v:[func:%v,file:%v,line:%v]\n", i, runtime.FuncForPC(funcName).Name(), fileName, line)
			} else {
				break
			}
		}
	}
}

func SafeCall(logger LoggerI) {
	defer PrintPanicStack(logger)
	panic("i'm die")
}

func main() {
	i := 0
	logger := log.New(os.Stderr, "", log.LstdFlags)
	for ; i < 3; i++ {
		SafeCall(logger)
	}
}
